<?php
/**
 * Created by PhpStorm.
 * User: chennan
 * Date: 2017/11/28
 * Time: 22:09
 */

namespace common\business\department;

use common\business\DbHandler;
use common\business\EhrHelper;
use common\business\qywx\QywxDepartmentApiHandler;
use common\helpers\StringUtil;
use DeepCopy\f008\A;
use Yii;
use common\consts\CommonResources;
use common\consts\Consts;
use common\models\Department;
use common\models\kingdee\OrgAdmin;
use common\models\qywx\QywxDepartment;
use common\result\ActionResult;
use yii\db\Query;
use yii\helpers\Json;

class DepartmentService extends DbHandler
{
    /**
     * @var string
     */
    protected $_department_number;
    public function setDepartmentNumber($department_number){
        $this->_department_number = $department_number;
    }

    /**
     * @var integer
     */
    protected $_idx;

    /**
     * @var integer
     */
    protected $_lvl;

    /**
     * @var OrgAdmin
     */
    protected $_topOrg;

    /**
     * @var Department
     */
    protected $_topDepartment;
//    /**
//     * @var int
//     */
//    protected $_totalCount;
    /**
     * @param callback|null $writeBackHandler
     * @return ActionResult
     */
    public function sync($writeBackHandler = null) {
        $apiHandler = new DepartmentApiHandler();

        $totalResult = new ActionResult();
        $isSyncTopSuccess = $this->syncTopOrgAndTopDepartment($totalResult, $writeBackHandler);
        if (!$isSyncTopSuccess){
            return new ActionResult(false, CommonResources::ACTION_FAIL_MSG('Sync', 'Department', $this->getErrorsMessage()));
        }

        $this->syncChildrenWithParentDepartment($this->_topOrg, $this->_topDepartment, $totalResult, $writeBackHandler);
        $this->_topDepartment->rgt = ++$this->_idx;
        $updateResult = $apiHandler->updateDepartment($this->_topDepartment);
        if (!$updateResult->isSuccess){
            $totalResult->addSubResult($updateResult);
            $this->executeWriteBackHandlerNoTotal($totalResult, $writeBackHandler);
        }
        return $totalResult;
    }

    /**
     * 需要找到最顶层Org，并且寻找企业微信是是否有这个节点，如果名字不一样要更新
     * @param $totalResult ActionResult
     * @param callback|null $writeBackHandler
     * @return bool
     */
    protected function syncTopOrgAndTopDepartment($totalResult, $writeBackHandler = null){
        $topIsRoot = false;
        $apiHandler = new DepartmentApiHandler();

        $isSkipped = false;

        if(!StringUtil::isNullOrWhiteSpace($this->_department_number)){
            $topOrg = OrgAdmin::findOne([
                'FNUMBER' => $this->_department_number,
            ]);
            $topIsRoot = false;

            if ($topOrg->FPARENTID == null){
                $this->_idx = 0;
                $this->_lvl = 0;
            }
            else {
                $topParentOrg = OrgAdmin::findOne([
                    'FID' => $topOrg->FPARENTID,
                ]);
                $topParentDepartment = Department::findOne(['number' => $topParentOrg->FNUMBER]);
                $this->_idx = $topParentDepartment->lft;
                $this->_lvl = $topParentDepartment->lvl;
            }
        }
//        否则拿顶层节点
        else{
            $topOrg = OrgAdmin::findOne([
                'FPARENTID' => null,
            ]);
            $topIsRoot = true;
            $this->_idx = 0;
        }

        if (!$topOrg)
        {
            $this->addError('Find Top Org', 'Top Org Not Found');
            $totalResult->addSubResult(new ActionResult(false, $this->getErrorsMessage()));
            $this->executeWriteBackHandlerNoTotal($totalResult, $writeBackHandler);
            return false;
        }

        if ($topIsRoot){
            $topDepartment = Department::findOne([
                'name' => EhrHelper::getName4QywxDepartment($topOrg),
                'number' => $topOrg->FNUMBER,
                'parent_id' => null,
            ]);
        }
        else {
            Department::deleteAll(
                'number=:number and name<>:name',
                [
                    ':number' => $topOrg->FNUMBER,
                    ':name' => EhrHelper::getName4QywxDepartment($topOrg),
                ]
            );

            $topDepartment = Department::findOne([
                'name' => EhrHelper::getName4QywxDepartment($topOrg),
                'number' => $topOrg->FNUMBER,
            ]);
        }

        if (!$topDepartment){
            $topDepartment = new Department([
                'name' =>  EhrHelper::getName4QywxDepartment($topOrg),
                'display_name' => $topOrg->FDISPLAYNAME_L2,
                'kd_id' => $topOrg->FID,
                'number' => $topOrg->FNUMBER,
                'mdm_id' => $topOrg->FBASEDUTY_L2,
                'hr_status' => Consts::SYNC_STATUS_FINISHED,
                'active' => Consts::YES,
                'visible' => Consts::YES,
                'collapsed' => Consts::YES,
                'movable_u' => Consts::YES,
                'movable_d' => Consts::YES,
                'movable_l' => Consts::YES,
                'movable_r' => Consts::YES,
                'removable' => Consts::YES,
            ]);
            $topDepartment->setLayer(EhrHelper::getOrgLayerTypeById($topOrg->FLAYERTYPEID));
//            企业微信号赋值
            $topDepartment->qywx_id = $topOrg->FCODE;
            $topDepartment->lvl =  ++$this->_lvl;
            $topDepartment->lft = ++$this->_idx;

            $createResult = $apiHandler->createDepartment($topDepartment);
            if (!$createResult->isSuccess){
                $totalResult->addSubResult($createResult);
                $this->executeWriteBackHandlerNoTotal($totalResult, $writeBackHandler);
                return false;
            }

            $topDepartment = Department::findOne([
                'number' => $topOrg->FNUMBER
            ]);
        }

        if ($topDepartment->hr_status == Consts::SYNC_STATUS_SYNCHRONIZING) {
            $this->addError('Sync Top', 'Other Thread is Syncing this record now.');
            $totalResult->addSubResult(new ActionResult(false, $this->getErrorsMessage(), true));
            $this->executeWriteBackHandlerNoTotal($totalResult, $writeBackHandler);
            return false;
        }
        //状态变成更新中
        $topDepartment->hr_status = Consts::SYNC_STATUS_SYNCHRONIZING;
        $topDepartment->mdm_id = $topOrg->FBASEDUTY_L2;
        $topDepartment->number = $topOrg->FNUMBER;
        $topDepartment->kd_id = $topOrg->FID;
        $topDepartment->display_name = $topOrg->FDISPLAYNAME_L2;
//      企业微信号赋值
        $topDepartment->qywx_id = $topOrg->FCODE;
        $topDepartment->setLayer( EhrHelper::getOrgLayerTypeById($topOrg->FLAYERTYPEID));
        $topDepartment->active = Consts::YES;
        $topDepartment->visible = Consts::YES;
        $topDepartment->collapsed = Consts::YES;
        $topDepartment->movable_u = Consts::YES;
        $topDepartment->movable_d = Consts::YES;
        $topDepartment->movable_l = Consts::YES;
        $topDepartment->movable_r = Consts::YES;
        $topDepartment->removable = Consts::YES;

        $topDepartment->lvl = ++$this->_lvl;
        $topDepartment->lft = ++$this->_idx;
        //状态变成更新完成
        $topDepartment->hr_status = Consts::SYNC_STATUS_FINISHED;
        $updateResult = $apiHandler->updateDepartment($topDepartment);
        if (!$updateResult->isSuccess){
            $totalResult->addSubResult($updateResult);
            $this->executeWriteBackHandlerNoTotal($totalResult, $writeBackHandler);
            return false;
        }
        if ($updateResult->isSkipped)
            $isSkipped = true;

        $this->_topOrg =  $topOrg;
        $this->_topDepartment = $topDepartment;
        $totalResult->addSubResult(new ActionResult(true, CommonResources::ACTION_SUCCESS_MSG('Sync Top', 'Department'), $isSkipped));
        $this->executeWriteBackHandlerNoTotal($totalResult, $writeBackHandler);
        return true;
    }

    /**
     * @param $org OrgAdmin
     * @param $parentDepartment Department
     * @param $totalResult ActionResult
     * @param callback|null $writeBackHandler
     * @return Department
     */
    protected function syncSingleOrgWithParent($org, $parentDepartment, $totalResult, $writeBackHandler = null){
        $isSkipped = false;
        $apiHandler = new DepartmentApiHandler();

//        Department::deleteAll(
//            'number=:number and name<>:name',
//            [
//                ':number' => $parentDepartment->number,
//                ':name' => EhrHelper::getName4QywxDepartment($org),
//            ]
//        );

//        保险起见全部删掉重建 20180307
//        Department::deleteAll(            [
//            'number' => $org->FNUMBER,
//        ]);

//        先查同一个父节点下有没有同名的
        $departmentInDb = Department::findOne([
            'name' => EhrHelper::getName4QywxDepartment($org),
            'parent_number' => $parentDepartment->number,
        ]);

        if (!$departmentInDb){
//            查有没有同编号的
            $departmentInDb = Department::findOne([
                'number' => $org->FNUMBER,
            ]);
            if ($departmentInDb){
                $departmentInDb->name = EhrHelper::getName4QywxDepartment($org);
                $departmentInDb->display_name = $org->FDISPLAYNAME_L2;
            }
            else {
                $newDepartment = new Department([
                    'name' =>  EhrHelper::getName4QywxDepartment($org),
                    'display_name' => $org->FDISPLAYNAME_L2,
                    'parent_id' => $parentDepartment->id,
                    'parent_number' => $parentDepartment->parent_number,
                    'kd_id' => $org->FID,
                    'number' => $org->FNUMBER,
                    'mdm_id' => $org->FBASEDUTY_L2,
                    'parent_kd_id' => $parentDepartment->kd_id,
                    'parent_qywx_id' => $parentDepartment->qywx_id,
                    'hr_status' => Consts::SYNC_STATUS_FINISHED,
                    'active' => Consts::YES,
                    'visible' => Consts::YES,
                    'collapsed' => Consts::YES,
                    'movable_u' => Consts::YES,
                    'movable_d' => Consts::YES,
                    'movable_l' => Consts::YES,
                    'movable_r' => Consts::YES,
                    'removable' => Consts::YES,
                ]);
                $newDepartment->setLayer(EhrHelper::getOrgLayerTypeById($org->FLAYERTYPEID));
//            企业微信号赋值
                $newDepartment->qywx_id = $org->FCODE;
                $newDepartment->lvl = $parentDepartment->lvl + 1;
                $newDepartment->lft = ++$this->_idx;

                $createResult = $apiHandler->createDepartment($newDepartment);
                if (!$createResult->isSuccess){
                    $totalResult->addSubResult($createResult);
                    $this->executeWriteBackHandlerNoTotal($totalResult, $writeBackHandler);
                    return null;
                }

                $departmentInDb = Department::findOne([
                    'number' => $org->FNUMBER
                ]);
            }
        }

        if ($departmentInDb->hr_status == Consts::SYNC_STATUS_SYNCHRONIZING) {
            $this->addError('Sync Top', 'Other Thread is Syncing this record now.');
            $totalResult->addSubResult(new ActionResult(false, $this->getErrorsMessage(), true));
            $this->executeWriteBackHandlerNoTotal($totalResult, $writeBackHandler);
            return null;
        }
        //状态变成更新中
        $departmentInDb->hr_status = Consts::SYNC_STATUS_SYNCHRONIZING;
        $departmentInDb->mdm_id = $org->FBASEDUTY_L2;
        $departmentInDb->number = $org->FNUMBER;
        $departmentInDb->parent_number = $parentDepartment->number;
        $departmentInDb->setLayer(EhrHelper::getOrgLayerTypeById($org->FLAYERTYPEID));
        $departmentInDb->parent_id = $parentDepartment->id;
        $departmentInDb->kd_id = $org->FID;
        $departmentInDb->parent_kd_id = $org->FPARENTID;
        $departmentInDb->display_name = $org->FDISPLAYNAME_L2;
//        企业微信号赋值
        $departmentInDb->qywx_id = $org->FCODE;
        $departmentInDb->parent_qywx_id = $parentDepartment->qywx_id;
        $departmentInDb->active = Consts::YES;
        $departmentInDb->visible = Consts::YES;
        $departmentInDb->collapsed = Consts::YES;
        $departmentInDb->movable_u = Consts::YES;
        $departmentInDb->movable_d = Consts::YES;
        $departmentInDb->movable_l = Consts::YES;
        $departmentInDb->movable_r = Consts::YES;
        $departmentInDb->removable = Consts::YES;
        $departmentInDb->lvl = $parentDepartment->lvl + 1;
        $departmentInDb->lft = ++$this->_idx;
        //状态变成更新完成
        $departmentInDb->hr_status = Consts::SYNC_STATUS_FINISHED;
        $updateResult = $apiHandler->updateDepartment($departmentInDb);
        if (!$updateResult->isSuccess){
            $totalResult->addSubResult($updateResult);
            $this->executeWriteBackHandlerNoTotal($totalResult, $writeBackHandler);
            return null;
        }
        if ($updateResult->isSkipped)
            $isSkipped = true;

        $totalResult->addSubResult(new ActionResult(true, CommonResources::ACTION_SUCCESS_MSG('Sync Single', 'Department'), $isSkipped));
        $this->executeWriteBackHandlerNoTotal($totalResult, $writeBackHandler);
        return $departmentInDb;
    }

    /**
     * @param $parentOrg OrgAdmin
     * @param $parentDepartment Department
     * @param $totalResult ActionResult
     * @param callback|null $writeBackHandler
     */
    protected function syncChildrenWithParentDepartment($parentOrg, $parentDepartment, $totalResult, $writeBackHandler = null){
        $apiHandler = new DepartmentApiHandler();
        $childrenOrgs = OrgAdmin::findAll([
                'FPARENTID' => $parentOrg->FID,
            ]);
        if (sizeof($childrenOrgs) == 0){
            return;
        }
        foreach ($childrenOrgs as $childOrg){
            $childDepartment = $this->syncSingleOrgWithParent($childOrg, $parentDepartment, $totalResult, $writeBackHandler);
            if ($childDepartment){
                $this->syncChildrenWithParentDepartment($childOrg, $childDepartment, $totalResult, $writeBackHandler);

                $childDepartment->rgt = ++$this->_idx;
                $updateResult = $apiHandler->updateDepartment($childDepartment);
                if (!$updateResult->isSuccess){
                    $totalResult->addSubResult($updateResult);
                    $this->executeWriteBackHandlerNoTotal($totalResult, $writeBackHandler);
                }
            }
        }
    }

}